using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using WpfClient.Core.Communication;
using WpfClient.Core.Models;

namespace WpfClient.Application.ViewModels
{
    /// <summary>
    /// Socket通信管理ViewModel
    /// </summary>
    public partial class SocketCommunicationViewModel : BaseViewModel
    {
        private readonly ISocketCommunicationService _communicationService;
        private readonly ILogger<SocketCommunicationViewModel> _logger;

        [ObservableProperty]
        private bool _isServerRunning;

        [ObservableProperty]
        private int _serverPort = 8080;

        [ObservableProperty]
        private string _serverStatus = "未启动";

        [ObservableProperty]
        private int _connectedClientsCount;

        [ObservableProperty]
        private ObservableCollection<ClientInfo> _connectedClients = new();

        [ObservableProperty]
        private ClientInfo? _selectedClient;

        [ObservableProperty]
        private string _customDataHex = "55AA020101";

        [ObservableProperty]
        private ObservableCollection<string> _communicationLog = new();

        [ObservableProperty]
        private bool _autoScrollLog = true;

        public SocketCommunicationViewModel(
            ISocketCommunicationService communicationService,
            ILogger<SocketCommunicationViewModel> logger)
        {
            _communicationService = communicationService;
            _logger = logger;

            // 订阅通信服务事件
            _communicationService.ClientConnected += OnClientConnected;
            _communicationService.ClientDisconnected += OnClientDisconnected;
            _communicationService.StatusChanged += OnStatusChanged;

            _logger.LogInformation("SocketCommunicationViewModel 已初始化");
        }

        [RelayCommand(CanExecute = nameof(CanStartServer))]
        private async Task StartServerAsync()
        {
            try
            {
                _logger.LogInformation("用户请求启动Socket服务器，端口: {Port}", ServerPort);
                
                await _communicationService.StartAsync(ServerPort);
                IsServerRunning = true;
                ServerStatus = $"运行中 (端口: {ServerPort})";
                
                AddLogEntry($"服务器已启动，监听端口: {ServerPort}");
                _logger.LogInformation("Socket服务器启动成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动Socket服务器失败");
                AddLogEntry($"启动服务器失败: {ex.Message}");
                ServerStatus = "启动失败";
            }
        }

        [RelayCommand(CanExecute = nameof(CanStopServer))]
        private async Task StopServerAsync()
        {
            try
            {
                _logger.LogInformation("用户请求停止Socket服务器");
                
                await _communicationService.StopAsync();
                IsServerRunning = false;
                ServerStatus = "已停止";
                ConnectedClientsCount = 0;
                ConnectedClients.Clear();
                
                AddLogEntry("服务器已停止");
                _logger.LogInformation("Socket服务器已停止");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "停止Socket服务器失败");
                AddLogEntry($"停止服务器失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private async Task RefreshClientsAsync()
        {
            try
            {
                var clients = await _communicationService.GetConnectedClientsAsync();
                
                ConnectedClients.Clear();
                foreach (var client in clients)
                {
                    ConnectedClients.Add(client);
                }
                
                ConnectedClientsCount = ConnectedClients.Count;
                _logger.LogDebug("客户端列表已刷新，当前连接数: {Count}", ConnectedClientsCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "刷新客户端列表失败");
                AddLogEntry($"刷新客户端列表失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private async Task SendCommand_02_01_Async()
        {
            if (SelectedClient == null)
            {
                AddLogEntry("请先选择一个客户端");
                return;
            }

            try
            {
                var data = ProtocolCommands.CreateSendPacket_02_01();
                await _communicationService.QueueDataAsync(SelectedClient.Id, data);
                
                AddLogEntry($"已发送命令 02 01 到客户端 {SelectedClient.IpAddress}:{SelectedClient.Port}");
                _logger.LogInformation("发送命令 02 01 到客户端: {ClientId}", SelectedClient.Id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送命令 02 01 失败");
                AddLogEntry($"发送命令失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private async Task SendCommand_03_01_Async()
        {
            if (SelectedClient == null)
            {
                AddLogEntry("请先选择一个客户端");
                return;
            }

            try
            {
                var data = ProtocolCommands.CreateSendPacket_03_01();
                await _communicationService.QueueDataAsync(SelectedClient.Id, data);
                
                AddLogEntry($"已发送命令 03 01 到客户端 {SelectedClient.IpAddress}:{SelectedClient.Port}");
                _logger.LogInformation("发送命令 03 01 到客户端: {ClientId}", SelectedClient.Id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送命令 03 01 失败");
                AddLogEntry($"发送命令失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private async Task SendCustomDataAsync()
        {
            if (SelectedClient == null)
            {
                AddLogEntry("请先选择一个客户端");
                return;
            }

            if (string.IsNullOrWhiteSpace(CustomDataHex))
            {
                AddLogEntry("请输入要发送的十六进制数据");
                return;
            }

            try
            {
                // 解析十六进制字符串
                var cleanHex = CustomDataHex.Replace(" ", "").Replace("-", "");
                if (cleanHex.Length % 2 != 0)
                {
                    AddLogEntry("十六进制数据长度必须是偶数");
                    return;
                }

                var data = new byte[cleanHex.Length / 2];
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = Convert.ToByte(cleanHex.Substring(i * 2, 2), 16);
                }

                await _communicationService.QueueDataAsync(SelectedClient.Id, data);
                
                AddLogEntry($"已发送自定义数据到客户端 {SelectedClient.IpAddress}:{SelectedClient.Port}: {CustomDataHex}");
                _logger.LogInformation("发送自定义数据到客户端: {ClientId}, Data: {Data}", SelectedClient.Id, CustomDataHex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送自定义数据失败");
                AddLogEntry($"发送自定义数据失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private async Task SendToAllClientsAsync()
        {
            if (string.IsNullOrWhiteSpace(CustomDataHex))
            {
                AddLogEntry("请输入要发送的十六进制数据");
                return;
            }

            try
            {
                // 解析十六进制字符串
                var cleanHex = CustomDataHex.Replace(" ", "").Replace("-", "");
                if (cleanHex.Length % 2 != 0)
                {
                    AddLogEntry("十六进制数据长度必须是偶数");
                    return;
                }

                var data = new byte[cleanHex.Length / 2];
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = Convert.ToByte(cleanHex.Substring(i * 2, 2), 16);
                }

                await _communicationService.QueueDataToAllAsync(data);
                
                AddLogEntry($"已向所有客户端发送数据: {CustomDataHex}");
                _logger.LogInformation("向所有客户端发送数据: {Data}", CustomDataHex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "向所有客户端发送数据失败");
                AddLogEntry($"向所有客户端发送数据失败: {ex.Message}");
            }
        }

        [RelayCommand]
        private void ClearLog()
        {
            CommunicationLog.Clear();
            _logger.LogDebug("通信日志已清空");
        }

        private bool CanStartServer() => !IsServerRunning;
        private bool CanStopServer() => IsServerRunning;

        private void OnClientConnected(object? sender, ClientConnectedEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                ConnectedClients.Add(e.Client);
                ConnectedClientsCount = ConnectedClients.Count;
                AddLogEntry($"客户端连接: {e.Client.IpAddress}:{e.Client.Port}");
            });
        }

        private void OnClientDisconnected(object? sender, ClientDisconnectedEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                var clientToRemove = ConnectedClients.FirstOrDefault(c => c.Id == e.Client.Id);
                if (clientToRemove != null)
                {
                    ConnectedClients.Remove(clientToRemove);
                    ConnectedClientsCount = ConnectedClients.Count;
                }
                
                if (SelectedClient?.Id == e.Client.Id)
                {
                    SelectedClient = null;
                }
                
                AddLogEntry($"客户端断开: {e.Client.IpAddress}:{e.Client.Port} - {e.Reason}");
            });
        }

        private void OnStatusChanged(object? sender, CommunicationStatusEventArgs e)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(() =>
            {
                AddLogEntry($"状态: {e.Status}" + (string.IsNullOrEmpty(e.Details) ? "" : $" - {e.Details}"));
            });
        }

        private void AddLogEntry(string message)
        {
            var timestamp = DateTime.Now.ToString("HH:mm:ss");
            var logEntry = $"[{timestamp}] {message}";
            
            CommunicationLog.Add(logEntry);
            
            // 限制日志条数，避免内存占用过多
            if (CommunicationLog.Count > 1000)
            {
                CommunicationLog.RemoveAt(0);
            }
        }

        partial void OnSelectedClientChanged(ClientInfo? value)
        {
            // 可以在这里添加选中客户端变化时的逻辑
        }
    }
}